﻿#ifndef GAME_H
#define GAME_H

#include "Game/GameCore.h"
#include "WordLib.h"
#include "_Global/Speech/Speech.h"

#include <QThread>
#include <QWaitCondition>
#include <QMutex>
#include <QList>
#include <QByteArray>
#include <QDebug>


#define WAIT_GAME_TERMINATE_TIME 5000


class TcpSocket;
class Game : public GameCore
{
    Q_OBJECT
    Q_PROPERTY(QObject* wordLib READ wordLib)
    Q_PROPERTY(QObject* word READ word) //当前正在考的 单词 信息(qml用)
    Q_PROPERTY(bool netPlay READ netPlay) //当前正在考的 单词 信息(qml用)

//本类发出的信号
signals:
    //socket发送数据(主线程发送)
    void s_SendDataToServer(QByteArray data, quint8 outControlbyte);//发送数据

    //连击,参数:次数 和 是否断开
    void s_ContinualChoice(int continualTimes, bool bContinue);
    //神速,参数:时间
    void s_FastChoice(qreal time);

public:
    explicit Game(QObject *parent = nullptr);
    virtual ~Game() Q_DECL_OVERRIDE
    {
        TerminateGame(-1, GameCore::Game_Status_Terminated);
    }
    

//重载游戏框架

public:
    virtual int InitOnce() Q_DECL_OVERRIDE; //主线程中初始化(1次)

    virtual int InitOnceInThread() Q_DECL_OVERRIDE; //线程中初始化(1次)

    virtual int GameInit(int sr = -1) Q_DECL_OVERRIDE;

    virtual int GameOver() Q_DECL_OVERRIDE
    {
        ContinualChoice(-1,0);
        return GameCore::GameOver();
    }

    //强制结束游戏
    virtual void TerminateGame(int ret, _GameStatus status = Game_Status_Exit) Q_DECL_OVERRIDE
    {
        GameCore::TerminateGame(ret, status);
        //m_mutexNet.tryLock();
        //m_mutexQuestion.tryLock();

        //getDataList();
        //pMutexNet->lock();
        m_Producer.comingNetDataSemaphore();
        //pMutexNet->unlock();
        //pMutexData->tryLock();
        //releaseDataList();
        //questionFinished();

        sl_UserActionFinished();

        quit();
        if(!wait(WAIT_GAME_TERMINATE_TIME))  //返回true:线程已经退出
        {
            terminate();
            emit s_GameOver(gameStatus());
        }
    }

protected:
    virtual _GameStatus CheckGameOver() Q_DECL_OVERRIDE
    {
        _GameStatus status = GameCore::CheckGameOver();
        /*
        if(ret != Game_Status_Continue)
        {
            //exit();quit();
        }*/
        return gameStatus();
    }



//UI游戏框架

protected:
    //等待UI解锁进程
    virtual void WaitForUserAction() Q_DECL_OVERRIDE
    {
        //注意:
        //unlock状态下:unlock函数会出错;QWaitCondition::wait函数会出错
        //所以保持lock状态
        m_mutexUserAction.lock();
        if(gameStatus() != Game_Status_Continue)
        {
            m_mutexUserAction.unlock();
            return;
        }
        m_waitForUserAction.wait(&m_mutexUserAction);
        m_mutexUserAction.unlock();
        //m_mutexUserAction.tryLock();  //立即返回是否已锁定(肯定会锁定)


        //m_waitForUserAction.wait(&m_mutexUserAction);
        //m_waitForNet.wait(&m_mutexNet);
        //qDebug()<<"m_mutexUserAction lock1!!!";
        //m_mutex.unlock();
        //QMessageBox::information(nullptr,"a","wait1unlock0");
        //QMessageBox::information(nullptr,"a","unlock1");
        //QThread::currentThread()->wait()
    }

    /*
    virtual void WaitForNet() Q_DECL_OVERRIDE
    {
        qDebug()<<"m_mutexNet lock0!!!";
        m_mutexNet.lock();
        qDebug()<<"m_mutexNet lock1!!!";
    }*/

    /*
    virtual void WaitForQuestion()
    {
        //QMessageBox::information(nullptr,"a","lock0");
        //QMessageBox::information(nullptr,"a","lock1wait0");
        //m_mutex.lock();
        qDebug()<<"mutex2!!!";
        m_mutexUserAction.lock();
        //m_mutexQuestion.tryLock();
        //m_waitForQuestion.wait(&m_mutexQuestion);
        qDebug()<<"mutex3!!!";
        //m_mutexQuestion.unlock();
        //QMessageBox::information(nullptr,"a","wait1unlock0");
        //QMessageBox::information(nullptr,"a","unlock1");
        //QThread::currentThread()->wait()
    }*/

//qml信号槽
public slots:

    //回答完问题,接受qml回答问题
    //!!!注意:这里的答案,从s_Wenti传递的WordObj参数直接赋值过去了!!!
    /*virtual void questionFinished(int answerChoice = -1)
    {
        m_mutexUserAction.unlock();
        //m_waitForQuestion.wakeAll();
    }*/

    /*Q_INVOKABLE*/ virtual void sl_UserActionFinished() Q_DECL_OVERRIDE
    {
        //qDebug() << "sl_UserActionFinished线程:"<< QThread::currentThreadId();  // << ::GetCurrentThreadId()
        //qDebug()<<"m_mutexUserAction unlock0!!!";
        //m_mutexUserAction.tryLock();    //防止多个数据包到来时多次unlock
        //m_mutexUserAction.unlock();
        m_mutexUserAction.lock();
        m_waitForUserAction.wakeAll();
        m_mutexUserAction.unlock();
        //qDebug()<<"m_mutexUserAction unlock1!!!";
        //m_waitForUserAction.wakeAll();
        //qDebug()<<"wakeALL!!";
    }

    /*
    virtual void netFinished() Q_DECL_OVERRIDE
    {
        qDebug() << "netFinished线程:" << QThread::currentThreadId();
        qDebug()<<"m_mutexNet tryLock unlock0!!!" <<QThread::currentThreadId();;
        //m_mutexNet.tryLock();    //防止多个数据包到来时多次unlock
        //m_mutexNet.unlock();
        m_SemaphoreData.release();
        qDebug()<<"m_mutexNet tryLock unlock1!!!" << QThread::currentThreadId();;
        //m_waitForNet.wakeAll();
        //qDebug()<<"wakeALL!!";
    }*/


    //接受qml选择的武将(id为武将value)
    virtual int sl_qml_SelectedWuJiang(int wuJiangValue)
    {
        if(wuJiangValue < 0)
            return -1;

        if(m_mapWuJiangUsingTimes.contains(wuJiangValue))
            m_mapWuJiangUsingTimes[wuJiangValue]++;
        else
            m_mapWuJiangUsingTimes[wuJiangValue] = 1;

        m_arrayPlayer[m_nMyID].getWuJiang((_WuJiang::_Value)wuJiangValue);
        //m_arrayPlayer[m_nMyID].m_listWuJiangQu.at(0)->createWuJiang(wuJiangValue);
        //qDebug() << "[Game]选择武将:" << (_WuJiang::_Value)wuJiangValue;

        sl_UserActionFinished();
        return 0;
    }






//重载游戏逻辑
protected:
    //选择武将(count为玩家数)
    virtual _GameStatus ChoiceWuJiang(int count) Q_DECL_OVERRIDE;

    //洗牌ok
    //将qipaidui随机放入paidui中,将所有qipaidui的leixing置为 -1,
    virtual bool Xipai() Q_DECL_OVERRIDE;

    virtual _GameButtonValue ChuPai(int player, _GameChuPaiType nType, int nValue, int nParam1 = -1, int nParam2 = -1, QVariant nParam3 = -1, int nInitStep = 0, QString strMsg = "") Q_DECL_OVERRIDE;

    virtual bool WenTi(int player, QString msg, int time) Q_DECL_OVERRIDE;
    virtual int ShowPlayersArea(int player) Q_DECL_OVERRIDE
    {
        emit s_ShowPlayersArea(player);
        return 0;
    }
    virtual int HidePlayersArea() Q_DECL_OVERRIDE
    {
        emit s_ShowPlayersArea(-1);
        return 0;
    }

    virtual int ShaiDian() Q_DECL_OVERRIDE;



//游戏其他函数
public slots:
    //游戏线程提交给主线程 发送数据
    void SendDataToServer(QByteArray& data, quint8 outControlbyte = 0x20);

    //qml调用,点击牌
    void sl_qml_PokeClicked(bool bClicked, QVariant v)
    {
        int n = v.toInt();
        if(!(m_arrayPai[n].flags() & _BaseObject::Flag_Enable))
        {
            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID(hide):"<<this->iID << "zvalue" << zValue();
            return;
        }

        //if(mouseButton == Qt::LeftButton && (this->iFlag & GAME_POKE_FLAG_ENABLE))
        {
            _ClickPai_(m_arrayPai + n);
            //m_arrayPai[n].setSomeFlags(_BaseObject::Flag_Clicked);

            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID:"<<this->iID << "zvalue:" << zValue();
            //if(event->button() == Qt::LeftButton)
            //    QMessageBox::information(nullptr,"aa","aa");
            //emit s_ClickPai(m_DianJiPai);
            sl_UserActionFinished();
        }
    }

    //qml调用,点击牌
    void sl_qml_JiNengClicked(bool bClicked, QVariant v1, QVariant v2)
    {
        int n = v1.toInt();
        int player = v2.toInt();

        //if(m_arrayPlayer[player].m_listJiNengPai[n])
        _Pai *pJiNeng = (_Pai*)m_arrayPlayer[player].m_listJiNengPai.at(n);

        if(!(pJiNeng->flags() & _BaseObject::Flag_Enable))
        {
            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID(hide):"<<this->iID << "zvalue" << zValue();
            return;
        }

        //if(mouseButton == Qt::LeftButton && (this->iFlag & GAME_POKE_FLAG_ENABLE))
        {
            _ClickJiNeng_(pJiNeng);
            //pJiNeng.setSomeFlags(_BaseObject::Flag_Clicked);

            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID:"<<this->iID << "zvalue:" << zValue();
            //if(event->button() == Qt::LeftButton)
            //    QMessageBox::information(nullptr,"aa","aa");
            //emit s_ClickPai(m_DianJiPai);
            sl_UserActionFinished();
        }
    }

    //qml调用,点击玩家
    void sl_qml_PlayerClicked(bool bClicked, QVariant v)
    {
        //qDebug()<<v.toInt();
        //m_arrayPlayer[v.toInt()].setFlags(_BaseObject::Flag_Enable | _BaseObject::Flag_Clicked);
        //return;

        int n = v.toInt();
        if(!(m_arrayPlayer[n].flags() & _BaseObject::Flag_Enable))
        {
            qDebug()<<"Player DisEnable却可以点击?";
            //m_arrayPlayer[n].setSomeFlags(_BaseObject::Flag_Clicked);
            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID(hide):"<<this->iID << "zvalue" << zValue();
            return;
        }

        //if(mouseButton == Qt::LeftButton && (this->iFlag & GAME_POKE_FLAG_ENABLE))
        {
            _ClickPlayer_(n);
            //m_arrayPlayer[n].setSomeFlags(_BaseObject::Flag_Clicked);

            //qDebug()<<this->iType<<","<<this->iPositionPlayerID<<",ID:"<<this->iID << "zvalue:" << zValue();
            //if(event->button() == Qt::LeftButton)
            //    QMessageBox::information(nullptr,"aa","aa");
            //emit s_ClickPai(m_DianJiPai);
            sl_UserActionFinished();
        }
    }

    //-1:时间超时,0~2:确定/取消/弃牌按钮;
    void sl_qml_ButtonClicked(int button);

    //qml调用,调试
    void sl_qml_DebugButton(int button, QVariant v);


    //统计本玩家的单词
    //nCorrect=1正确,=0错误,=-1为结束统计;
    //time为选择用的时间
    void ContinualChoice(int nCorrect, double time)
    {
        if(nCorrect == 1)    //正确
        {
            m_pWordLib->m_nWordCount++;
            m_pWordLib->m_nCorrectCount++;

            if(time < 5000)
            {
                emit s_FastChoice(1);
                m_pWordLib->m_nFastChoice++;
            }
            m_pWordLib->m_nContinualChoice++;
            emit s_ContinualChoice(m_pWordLib->m_nContinualChoice, true);
        }
        else
        {
            //计算连击
            if(m_pWordLib->m_nContinualChoice > 2)
            {
                m_pWordLib->m_nContinualStatistics +=
                        (4 + (m_pWordLib->m_nContinualChoice - 2) +
                        (m_pWordLib->m_nContinualChoice - 2) * (m_pWordLib->m_nContinualChoice - 2 - 1) / 2);
                /*此公式是个等差数列
                    3    4 + 1
                    4    4 + 1 + 2
                    5    4 + 1 + 2 + 3
                    6    4 + 1 + 2 + 3 + 4
                */
                m_pWordLib->m_nContinualStatistics *= 2;
            }
            emit s_ContinualChoice(m_pWordLib->m_nContinualStatistics, false);
            m_pWordLib->m_nContinualChoice = 0;

            if(nCorrect == 0)
            {
                m_pWordLib->m_nWordCount++;
                m_pWordLib->m_nMistakeCount++;
            }
        }
    }

    int readWord(QString text)
    {
        return m_Speech.read(text);
    }

//属性
public:
    QObject* wordLib() const;

    QObject* word()// const
    {
        return &wordObj;
    }
    bool netPlay() const
    {
        return m_bNetPlay;
    }


public:
//UI游戏框架
    //QWaitCondition需要已锁的QMutex才能wait,wait时会将QMutex unlock!!
    QWaitCondition  m_waitForUserAction;
    QMutex          m_mutexUserAction;
    //bool            m_bAction;      //是否可以Wake工作线程,其实也可以不用

    //QWaitCondition  m_waitForQuestion;
    //QWaitCondition  m_waitForNet;
    //QMutex          m_mutexQuestion;

//网络游戏框架
    ProducerModel   m_Producer;
    TcpSocket       *m_pGameSocket;



public:
//游戏数据:
    WordLib         *m_pWordLib;        //配置(Manager赋值)和单词库
    _WordObject     wordObj;            //1个单词对象(qml暴露用)

    L_Speech        m_Speech;

//游戏配置
    bool            m_bNetPlay;
};

#endif //GAME_H
